#pragma once
#include <Poco/Observer.h>
#include <Poco/Task.h>
#include <Poco/TaskManager.h>
#include <Poco/TaskNotification.h>
#include <Poco/ThreadPool.h>

#include "MyFmt.h"

/// <summary>
/// 基础示例：启动一批任务
/// </summary>
/// A Task is a subclass of Runnable that has a name
/// and supports progress reporting and cancellation.
///
/// A TaskManager object can be used to take care of the lifecycle of a Task.
class MyTask2 : public Poco::Task
{
public:
    explicit MyTask2(const std::string& name, int duration, int prt = 1) : Task(name), _duration(duration), _prt(prt) {}

private:
    int _duration{};
    int _prt{1};
    /// Do whatever the task needs to do. Must be overridden by subclasses.// 必须实现
    void runTask() override
    {
        for (int i = 0; i < _duration; ++i)
        {
            /// Sets the task's progress.
            /// The value should be between 0.0 (just started) and 1.0 (completed).
            Task::setProgress(static_cast<float>(i + 1) / static_cast<float>(_duration));  // 0~1 的进度
            if (_duration % _prt == 0)
            {
                INFO("{} step {}", name(), i + 1)
            }
            /// Suspends the current thread for the specified amount of time.
            Task::sleep(1);
            if (Task::isCancelled())
            {  // 检查取消
                INFO("{} cancelled", name())
                return;
            }
        }
    }
};

///=========================== 使用默认线程池& 全局单例
#if 0
Poco::TaskManager tm;  // 不传 ThreadPool 时，自动使用 Poco::ThreadPool::defaultPool()
#endif

FnInInt TeRunTasks()
{
    MY_ECHO_FUN_NAME

    Poco::ThreadPool pool(2, 10);  // 最少2最大10线程
    Poco::TaskManager tm(pool);    // 关联线程池

    for (int i = 0; i < 10; ++i) tm.start(new MyTask2("task-" + std::to_string(i), 5));

    tm.joinAll();  // 阻塞等全部结束
    INFO("After Join")
    return 0;
}

///=========================== 任务取消演示
FnInInt TeCancelTasks()
{
    MY_ECHO_FUN_NAME

    Poco::TaskManager tm;
    MyTask2* t1 = new MyTask2("long-time", 2000, 200);
    tm.start(t1);

    /// Suspends the current thread for the specified amount of time.
    Poco::Thread::sleep(1000);  // 运行 1 秒
    INFOC("After sleep")
    t1->cancel();  // 请求取消

    /// Waits for the completion of all the threads
    /// in the TaskManager's thread pool.
    ///
    /// Note: joinAll() will wait for ALL tasks in the
    /// TaskManager's ThreadPool to complete. If the
    /// ThreadPool has threads created by other
    /// facilities, these threads must also complete
    /// before joinAll() can return.
    //tm.joinAll();

    return 0;
}

///=========================== 监听任务事件（进度、完成、失败）
class ProgressHandler
{
public:
    void onProgress(Poco::TaskProgressNotification* pNf)
    {
        INFO("{} progress: {}%", pNf->task()->name(), pNf->progress() * 100);
        /// and deletes the object if the count reaches zero.
        pNf->release();
    }
    void onFinished(Poco::TaskFinishedNotification* pNf)
    {
        INFO("{} finished", pNf->task()->name());
        pNf->release();
    }
};

///===========================
FnInInt TeListenTask()
{
    MY_ECHO_FUN_NAME

    Poco::TaskManager tm;
    ProgressHandler ph;
    tm.addObserver(Poco::Observer<ProgressHandler, Poco::TaskProgressNotification>(ph, &ProgressHandler::onProgress));
    tm.addObserver(Poco::Observer<ProgressHandler, Poco::TaskFinishedNotification>(ph, &ProgressHandler::onFinished));

    tm.start(new MyTask2("A", 50));
    tm.start(new MyTask2("B", 50));
    tm.joinAll();

    return 0;
}